﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows.Data;
using System.ComponentModel;
using System.Linq.Expressions;
/*
namespace MoneyManagerNET.Presentation.Infrastructure
{
    public static class Generic
    {
        public static TService GetService<TService>(this IServiceProvider isp)
            where TService : class
        {
            return isp.GetService(typeof(TService))
                as TService;
        }
    }

    public class LambdaExtension : MarkupExtension
    {
        public string Code { get; private set; }

        public LambdaExtension()
        {

        }
        public LambdaExtension(string _code):this()
        {
            this.Code = _code;
        }

        public override object ProvideValue(IServiceProvider isp)
        {
            IProvideValueTarget tp = isp.GetService<IProvideValueTarget>();
            if (tp.TargetObject is Binding) return new SingleConverter(this.Code);
            //if (tp.TargetObject is MultiBindingExtension) 
                return new MultiConverter(this.Code);
            //return null;
        }
    }

    class SingleConverter : IValueConverter
    {
        public Delegate Operation { get; private set; }
        public string Code { get; private set; }

        public SingleConverter(string _code)
        {
            this.Code = _code;
        }

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (this.Operation == null)
            {
                ConstructOperation(value, targetType);
            }
            return this.Operation.DynamicInvoke(value);
        }

        private void ConstructOperation(object value, Type targetType)
        {
            int opi = this.Code.IndexOf("=>");
            if (opi < 0) throw new Exception("No lambda operator =>");
            string param = this.Code.Substring(0, opi);
            string body = this.Code.Substring(opi + 2);
            ParameterExpression p = Expression.Parameter(value.GetType(), param);
            LambdaExpression lambda = DynamicExpression.ParseLambda(new ParameterExpression[] { p }, targetType, body, value);
            this.Operation = lambda.Compile();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    class MultiConverter : IMultiValueConverter
    {
        public Delegate Operation { get; private set; }
        public string Code { get; private set; }

        public MultiConverter(string _code)
        {
            this.Code = _code;
        }

        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (this.Operation == null)
            {
                int paramSideLength = this.Code.IndexOf("=>");
                if (paramSideLength < 0) throw new Exception("No lambda operator =>");
                string paramSide = this.Code.Substring(0, paramSideLength);
                string[] paramNames = paramSide.Split(',');
                string bodySide = this.Code.Substring(paramSideLength + 2);
                ParameterExpression[] pes = new ParameterExpression[paramNames.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    pes[i] = Expression.Parameter(values[i].GetType(), paramNames[i]);
                }
                LambdaExpression lambda = DynamicExpression.ParseLambda(pes, targetType, bodySide, values);
                this.Operation = lambda.Compile();
            }
            return this.Operation.DynamicInvoke(values);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
*/